<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

    <script>
        /* 
            1-lodash 深拷贝  cloneDeep (常用)
            2- 
                JSON.parse(JSON.stringify(obj))  对象转为字符串， 
                再利用parse方法解析字符串-创建一个新对象

                缺点：
                    1- json数据 不能存 函数（数字，字符串，null，对象 数组 ）
                    2-如果存在循环引用就会报错  TypeError: Converting circular structure to JSON
        
           3- 封装 cloneDeep函数  (通过循环遍历 递归调用自己)    
           
           
           一般有拷贝的需求--用浅拷贝就行了
           什么是用深拷贝（改了一个对象，发现另一个对象也改变了-----写编辑功能）
        
        */
        var son = { name: "张三丰", child: { name: "张四" } };

        var zhangsan = {
            name: "zhangsan",
            age: 18,
            child: son,
            run: function () { }
        };

        // 这句话 会产生循环引用
        son.father = zhangsan;

        console.log(zhangsan);

        // 1-lodash 深拷贝  cloneDeep (常用)

        // var lisi = _.cloneDeep(zhangsan);

        // 2 - JSON.parse(JSON.stringify(obj))  对象转为字符串， 再利用parse方法解析字符串 - 创建一个新对象

        // console.log(JSON.stringify(zhangsan));
        // var lisi = JSON.parse(JSON.stringify(zhangsan));

        // console.log(lisi);

        // 3-封装 cloneDeep函数   

        // 这个方法类似_.clone，除了它会递归拷贝 value


        function cloneDeep(obj, wm = new WeakMap()) {
            if (wm.has(obj)) {
                return obj;
            } else {
                wm.set(obj, 1)
            }
            console.log('cloneDeep 执行了一次 ', obj);
            // 遍历 obj 的所有属性， 把属性 都添加到一个 新对象中 
            var newObj = {}
            for (var key in obj) {
                //key 属性名
                // obj[key] 属性值
                var value = obj[key];
                //判断value 是不是一个对象-创建newValue
                // 如果是 调用自己 
                if (typeof value === 'object') {

                    // 调用自己 ，得到新的newValue
                    let newValue = cloneDeep(value, wm);

                    newObj[key] = newValue


                } else {
                    //value不是一个对象
                    // 把属性 都添加到一个 新对象中 
                    newObj[key] = value;
                }



            }
            // 返回这个新对象
            return newObj

        }

        let lisi = cloneDeep(zhangsan)


        console.log(lisi);


        console.log(lisi === zhangsan);//false
        console.log(lisi.child === zhangsan.child);//false
        console.log(lisi.child.child === zhangsan.child.child);//false
    </script>

</body>

</html>